www.gusucode.com > matlab编程多天线姿态确定工具箱,包括星历读取、单点定位、差分定位、坐标转换、定姿 > matlab编程多天线姿态确定工具箱,包括星历读取、单点定位、差分定位、坐标转换、定姿/A MATLAB toolbox for attitude determination with GPS multi-antenna systems/AttDet_16_3_2009/AttDet/mainpro_ph.m
%%======================================== %% Toolbox for attitude determination %% Zhen Dai %% dai@zess.uni-siegen.de %% ZESS, University of Siegen, Germany %% Last Modified : 1.Sep.2008 %%======================================== %% Functions: %% Main program for attitude determination using carrier phase. %% Input parameters: %% ------- From data file DataSatRecord ------: %% mCommonEpoch %% -> Synchronized epochs for all antennas %% mEpochStr %% -> Epochs expressed in string %% mMeasurement %% -> Code data, phase data, satellite visibility %% maskangle %% -> Satellite elevation mask angle (cut-off angle) %% smoothing_interval %% -> Smoothing inteval, i.e. the length of accumulated data %% for HATCH smoothing %% mBaseline %% -> Magnitude of the baselines %% %% ------- From data file RinexNav ------: %% mEphemerides %% -> Ephemerides parameters needed for the calculation of %% satellite positions and the acquirement of some %% corrections %% mEphTime %% -> Time tag of each ephemerides. It is used to search for the %% proper ephemerides for a specific satelilte at a specific time %% ------- From mat file "ambiguity" ------: %% mAmbiguity %% -> Double-differenced phase ambiguities of each antenna%% %% Output: %% mAttitudeRecordLSQLinear %% -> Attitude parameters from least squares estimation %% mAttitudeRecordDirect %% -> Attitude parameters from direct attitude computation %% Remarks: %% 1. Result will be illustrated and also saved into the data file %% "Results.txt" clear all clc %% ******************************************************************** %% Constant Definition %% ******************************************************************** sol=299792458; %% Speed of light freq1=1575.42e6; %%frequency of L1 lambda1=sol/(freq1);%% lambda on L1 totalGPSsatellite=32; %% Assuming that there are maximal 32 GPS satellites %% Some global variables for the ephemerides global mEphTime mEphemerides %% ******************************************************************** %% Load Measurement %% ******************************************************************** load DataSatRecord load RinexNav load ambiguity %% ******************************************************************** %% Initialization %% ******************************************************************** totalepoch=size(mCommonEpoch,1); %% how many synchonized epochs to be proessed totalantenna=size(mMeasurement,1); % how many antenna/receiver pairs %% If baselines are identified, then extract them. if num_baseline~=0 % Baseline 1-2 1-3 2-3 b12=mBaseline(1,1); b13=mBaseline(2,1); b23=mBaseline(3,1); % Baseline 1-4 2-4 3-4, 1-5 2-5 3-5, 1-6 2-6 3-6 mBaselineAdd=[]; for antid=4:1:totalantenna, mBaselineAdd(antid-3,1:3)= mBaseline(antid,1:3); end else %% if no baseline given, then we consider the first 3 antennas totalantenna=3; end %% some matrix for recording the estimated attitude parameters %% 1st epoch will be deleted mAttitudeRecordDirect=zeros(totalepoch-1,3); mAttitudeRecordLSQMatrix=zeros(totalepoch-1,3); mAttitudeRecordLSQLinear=zeros(totalepoch-1,3); %% Initilize the matrix recording measurement mPhase=zeros(totalantenna,totalGPSsatellite,totalepoch); mCode=zeros(totalantenna,totalGPSsatellite,totalepoch); mCodeSmoothed=zeros(totalantenna,totalGPSsatellite,totalepoch); mSat=zeros(totalantenna,totalGPSsatellite,totalepoch); mSatPos=zeros(totalantenna,totalGPSsatellite,totalepoch,3); vKeySat=zeros(totalepoch,1); %% ******************************************************************** %% Data extraction %% ******************************************************************** %% Extract the measurement and satellite information %% For each matrix including phase , code, and sat visibility: %% 1st dimension : receiver ID( 1~n), No.1 is master antenna %% 2nd dimension: satelite ID (1~totalGPSsatellite of 32) %% 3rd dimension : epoch (1~totalepoch) %% ******************************************************************** for epoch=1:1:totalepoch,%% Loop for epochs for antid=1:1:totalantenna, %% Loop for receiver %% Satellites visibility. 1=visible mSat(antid,1:totalGPSsatellite,epoch)=squeeze(squeeze(mMeasurement(antid,epoch,1,:))); for k=1:1:totalGPSsatellite, %% Loop for satelltes of current epoch if mSat(antid,k,epoch)==1, mPhase(antid,k,epoch)=mMeasurement(antid,epoch,3,k);%% Phase data mCode(antid,k,epoch)=mMeasurement(antid,epoch,2,k); %% Code range without smoothing end end end end %% ******************************************************************** %% Smoothing code by carrier phase %% ******************************************************************** mCodeSmoothed=zeros(totalantenna,totalGPSsatellite,totalepoch); for i=1:1:totalantenna, clear mCodeTemp mRawCode=squeeze(mCode(i,:,:)); mRawPhase=squeeze(mPhase(i,:,:)); mCodeSmoothed(i,:,:)=Smoothing(mRawCode,mRawPhase,smoothing_interval); end %% ******************************************************************** %% Single point positioning for master antenna %% ******************************************************************** waitbar_sp = waitbar(0,'Single point positioning......'); %% Satellite clock correction vSatClockCor=zeros(1, totalGPSsatellite); %% Satellite position in ECEF mSatPos=zeros(totalantenna,totalepoch,totalGPSsatellite,3); for epoch = 1:1:totalepoch, %%Loop for epoch mSatPosCur=zeros(totalGPSsatellite,3); %% Satellite positions of current epoch vCodeCur=zeros(1,totalGPSsatellite); %% Code data of current epoch vPhaseCur=zeros(1,totalGPSsatellite); %% Phase data of current epoch vCodeSmoothedCur=zeros(1,totalGPSsatellite); %% Smoothed code data of current epoch clear vSatUsed vElevationAngle %% Extract the satellite info and measurement for master antenna vSatIDs=find(squeeze(mSat(1,1:totalGPSsatellite,epoch))~=0);%% visible satellites PRNs of current epoch vCodeCur=mCode(1,:,epoch); vPhaseCur=mPhase(1,:,epoch); vCodeSmoothedCur=mCodeSmoothed(1,:,epoch); %% Initialization for the first epoch if epoch==1, vInitPos=[1 1 1]; %% The initial guess of adjustment receiver_clock=0; %% Receiver clock error vEpheEopchs=zeros(totalGPSsatellite,1); %% Index of ephemerides paragrath used vGroupDelay=zeros(1, totalGPSsatellite); %% Group delay error vSatClockCor=zeros(1, totalGPSsatellite);%% Satellite clock error else %% if not the first epoch, the LSQ adjustment starts from the position of last epoch vInitPos(1:3)=mAntXYZAll(1,epoch-1,1:3); end time=mCommonEpoch(epoch); %% "Second of the week " of current epoch %% Calculate the coordinate of satellites for i=1:1:length(vSatIDs), satid=vSatIDs(i); %% Satellite PRN %% Find a proper ephemerides vEpheEopchs(satid)=SeekEpheEpoch(time,satid); %% Estimate the transit time of GPS signal. transit_time=vCodeCur(satid)/sol+vSatClockCor(satid)-receiver_clock-vGroupDelay(satid); %% Calculate the satellite position [vSatPosNoRotation ,vSatClockCor(satid),vGroupDelay(satid)]= GetSatPosECEF(satid,vEpheEopchs(satid),time,transit_time ); %% Filter out the satellite with low elevation angle vSatENU= ECEF2ENU(vSatPosNoRotation,vInitPos'); vElevationAngle(i) = atan(vSatENU(3)/norm(vSatENU(1:2)))*180/pi; if (vElevationAngle(i) < maskangle) && (epoch~=1), low_angle_id=satid; %% Delete this satellite from the matrix recording %% satellite PRNs, this satellite will then not be used %% any more in the following parts. mSat(1,satid,epoch)=0; continue; %% go to process the next satellite end %% Correct the code data by removing receiver clock error, %% satellite clock error, group delay %% For smoothed and raw code data vCorrectedCodeSmoothed(satid)=vCodeSmoothedCur(satid)-receiver_clock*sol+... vSatClockCor(satid)*sol-vGroupDelay(satid)*sol; vCorrectedCode(satid)=vCodeCur(satid)-receiver_clock*sol+... vSatClockCor(satid)*sol-vGroupDelay(satid)*sol; %% Implement the earth rotation to the satellite vSatXYZ=EarthRotation(transit_time,vSatPosNoRotation); %% Save the satellite positions of this epoch for single point posiitoning mSatPosCur(satid,1:3)= vSatXYZ; %% Save the satellite positions for future differential positioning mSatPos(1,epoch,satid,1:3)= vSatXYZ; end %% End of loop for satellites %% Satellites used for the positioning at current epoch vSatUsed=find(squeeze(squeeze(mSat(1,:,epoch)))~=0); %% For master antenna, choose the key satellite for future DGPS %% Key satellite implies the satellite having the highest %% elevation angle herein. %% For the post-processing and for the ambiguity resolution, the %% key satellite could also be chosen as the satellite having the %% longest visibility within a specific time span. max_elevation=max(vElevationAngle); vKeySat(epoch)=vSatIDs(find(vElevationAngle==max_elevation)); %% Single point positioning using smoothed code data [vAntPos_sm,receiver_clock]=SinglePointGPS(vCorrectedCodeSmoothed,mSatPosCur,vSatUsed,vInitPos); mAntXYZAll(1,epoch,1:3)=vAntPos_sm; str=sprintf('Single point positioning %2.0f%%%', epoch/totalepoch*100); waitbar(epoch/totalepoch,waitbar_sp,str) end %% End of loop for epochs close (waitbar_sp) %% ******************************************************************** %% Differential GPS positioning %% ******************************************************************** waitbar_DGPS = waitbar(0,'Differential Positioning'); for epoch=1:1:totalepoch, %% Loop for epoch %% ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ %% Get the corresponding data of the master antenna %%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Data of master antenna at this epoch vSatIDMaster=find(squeeze(squeeze(mSat(1,:,epoch)))~=0); vCodeMaster=mCode(1,:,epoch); vPhaseMaster=mPhase(1,:,epoch); vCodeSmoothedMaster=mCodeSmoothed(1,:,epoch); mSatPosMaster=squeeze(mSatPos(1,epoch,:,1:3)); %% Estimated positiong of master antenna from single point positioning vMasterPosition=squeeze(mAntXYZAll(1, epoch,1:3)); for antid=2:1:totalantenna, %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Get the data from slave antenna %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ clear mSlaveSatID vElevationAngle %% Satellite IDs for slave antenna given in a compact format vSatIDSlave=find(squeeze(squeeze(mSat(antid,:,epoch)))~=0); %% Code data of slave antenna (compact) vCodeSlave=mCode(antid,:,epoch); vPhaseSlave=mPhase(antid,:,epoch); vCodeSmoothedSlave=mCodeSmoothed(antid,:,epoch); %% Search for the common satellites of master and this slave antenna vCommonSatID= intersect(vSatIDSlave,vSatIDMaster); satnum_common=length(vCommonSatID); %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Calculate the satellite position for slave antenna %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for i=1:1:satnum_common, satid=vCommonSatID(i); %% Satellite PRN %% Find a proper ephemerides paragraph time=mCommonEpoch(epoch); %% "Second of the week " of current epoch eph_epoch=SeekEpheEpoch(time,satid); %% "True" distance for master antenna dis_true_master=norm(vMasterPosition-mSatPosMaster(satid,:)'); %% "True" distance for slave antenna dis_true_slave=dis_true_master-vCodeMaster(satid)+vCodeSlave(satid); %% Estimate the transit time of GPS signal. transit_time=dis_true_slave/sol; %% Calculate the satellite position [vSatPosNoRotation ,sat_clock_err,sat_group_delay]= GetSatPosECEF(satid,eph_epoch,time,transit_time ); %% Implement the earth rotation to the satellite vSatXYZ=EarthRotation(transit_time,vSatPosNoRotation); %% Satellite position of slave antenna mSatPosSlave(satid,:)=vSatXYZ; end %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Find the data from common satellites to construct baselines %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Get the key satellite ID for the construction of differential %% observation equation key_sat_id=vKeySat(epoch); %% Pick up the common visible satellites for DGPS processing mCommonSatPosSlave=zeros(totalGPSsatellite,3); mCommonSatPosMaster=zeros(totalGPSsatellite,3); mCommonSatPosSlave(vCommonSatID,:)=mSatPosSlave(vCommonSatID,:); mCommonSatPosMaster(vCommonSatID,:)=mSatPosMaster(vCommonSatID,:); %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Get the ambiguity %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vN= mAmbiguity(antid-1,:); %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% DGPS solution %%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vSlavePosition_phase =DGPS_phase(mCommonSatPosMaster,mCommonSatPosSlave,vPhaseMaster,.... vPhaseSlave, key_sat_id,vCommonSatID,vN,vMasterPosition ); %% Record the slave antenna coordinates and baselines %% for further attitude determination processing mAntXYZAll(antid,epoch,1:3)=vSlavePosition_phase; if num_baseline~=0, %% Calculate the 3D error in the estimated baselines. if antid==2, baseline_true=b12; elseif antid==3, baseline_true=b13; elseif antid>3, baseline_true=mBaselineAdd(antid-3,1); end mBaselineEst(epoch,antid)=norm(vSlavePosition_phase-vMasterPosition'); mBaselineErr( epoch,antid )=mBaselineEst(epoch,antid)-baseline_true; end %% Save the local level coordinates of the slave antenna mAntENUAll(antid,epoch,1:3)=ECEF2ENU(vSlavePosition_phase,vMasterPosition); end str=sprintf('Differential GPS processing %2.0f%%%', epoch/totalepoch*100 ); waitbar(epoch/totalepoch,waitbar_DGPS,str) end %% End DGPS close (waitbar_DGPS) %% Since the results of 1st epoch are always of low quality, we therefore %% delete this value. if num_baseline~=0, mBaselineEst(1,:)=[]; mBaselineErr(1,:)=[]; end mAntXYZAll(:,1,:)=[]; mAntENUAll(:,1,:)=[]; totalepoch=totalepoch-1; %% If baselines are identified, then display the baseline error if num_baseline~=0, %% Show baselines errors for antid=2:1:totalantenna, vBaselineErr=mBaselineErr(:,antid); title_str=sprintf('Estimated baseline 3D error between antenna 1 and %d',antid); DisplayBaselineErr(vBaselineErr,title_str); end end %% ################################################### %% ################################################### %% Attitude determination %% ################################################### %% ################################################### %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Direct computation %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ waitbar_attitude1=waitbar(0,'Direct attitude computation'); for epoch=1:1:totalepoch, %% Local level frame for slave antennas %% only consider the antenna 1-3 and ignore the others for antid=1:1:3, mAntLocal(antid,1:3)=squeeze(mAntENUAll(antid,epoch,1:3)); end %% Attitude determination by direct computation %% Antenna 1 is [0 0 0] %% Use only the local level coordinate of antenna 2 and 3 [yaw_deg_direct,roll_deg_direct,pitch_deg_direct]=AD_Direct(mAntLocal(2,:),mAntLocal(3,:)); %% Save the data mAttitudeRecordDirect(epoch,1:3)=[yaw_deg_direct roll_deg_direct pitch_deg_direct ]; str=sprintf('Direct attitude computation %2.0f%%%', epoch/totalepoch*100); waitbar(epoch/totalepoch,waitbar_attitude1,str) end close (waitbar_attitude1) %% Demonstrate the result DrawAttitudeFigure(mAttitudeRecordDirect, 'Attitude parameters based on direct computation') SaveResultInFile(mAttitudeRecordDirect,mEpochStr, 'Result from direct attitude determination using CARRIER PHASE','Results.txt') %% Once no baseline identified, then exit. if num_baseline==0, !results.txt; return; end %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% Attitude computation by LSQ %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %% ~~~~~ Step 1: Calculate the antenna body frame ~~~~~ mAntBody=GetBodyCoordinates(b12,b13,b23,mBaselineAdd); %% Knowing only the magnitude of baselines we can not specify the Z value %% of the antenna body frame for the antenna 4,5,6. We should employ the %% calculated attitude parameters and the local level coordinate to derive %% the estimated antenna body frame. The estimated antenna body frame will %% help the determination of the Z value. if totalantenna>=4, %% Choose the first 50 epoch to calculate the antenna body frame based on %% the attitude parameters obtained from the direct computation if totalepoch>50, testepoch=50; else testepoch=totalepoch; end %% Now get the sign of the Z value in the antenna body frame by using the %% relationship: Body Frame=Rotation matrix* Local level frame, where the %% rotation matrix is obtained from the attitude parameters based on the %% direct attitude computation. for epoch=1:1:testepoch, mAntLocal =squeeze(mAntENUAll(:,epoch,1:3)); mR=GetCombinedRotationMatrix(mAttitudeRecordDirect(epoch,1),... mAttitudeRecordDirect(epoch,2),mAttitudeRecordDirect(epoch,3)); mBodyTemp=(mR*mAntLocal')'; for i=4:1:totalantenna, mSign(epoch,i)=mBodyTemp(i,3)/abs(mBodyTemp(i,3)); end end vSumSign=sum(mSign); %% If 80% of the Z values are of the same sign, we then consider it as the %% correct sign. Otherwise the user has to specify the sign(s). for antid=4:1:totalantenna, if abs(vSumSign(antid)/testepoch)>0.8, sign_z=vSumSign(antid)/abs(vSumSign(antid)); mAntBody(antid,3)=abs(mAntBody(antid,3))*sign_z; else str=sprintf('Can not determine the Z value of antenna body frame of antenna %d, use default value instead',antid); msgbox(str); end end end %% ~~~~~ Step 2: Start attitude calculation LSQ ~~~~~ waitbar_attitude2 = waitbar(0,'Attitude determination'); for epoch=1:1:totalepoch, %% Local level frame for slave antennas mAntLocal =squeeze(mAntENUAll(:,epoch,1:3)); %% Attitude determination by applying LSQ [yaw_deg_lsq,roll_deg_lsq,pitch_deg_lsq]=AD_LSQ(mAntLocal ,mAntBody ,0,0,0); %% Save the data mAttitudeRecordLSQLinear(epoch,1:3)=[yaw_deg_lsq roll_deg_lsq pitch_deg_lsq]; str=sprintf('Least squares attitude determination %2.0f%%%', epoch/totalepoch*100); waitbar(epoch/totalepoch,waitbar_attitude2,str) end %% close (waitbar_attitude2) DrawAttitudeFigure(mAttitudeRecordLSQLinear,'Attitude parameters based on linearized least squares adjustment') SaveResultInFile(mAttitudeRecordLSQLinear,mEpochStr, 'Result from least squares estimation using CARRIER PHASE','Results.txt') type('results.txt');